﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms.Integration;
using System.IO;
using System.Windows.Interop;

namespace ClipPlayer
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IDisposable
    {
        CSimpleConfig sCfg = new CSimpleConfig();
        //private const string HINT_FILE_NAME = ".ClipPlayer.hint";

        AxAXVLC.AxVLCPlugin2 vlc = new AxAXVLC.AxVLCPlugin2();

        private List<MediaFile> filesToPlay = new List<MediaFile>();
        private int currentPlaying = 0;
        //
        //
        internal DbStatistics stat = null;//new DbStatistics(DbStatistics. dbConnectionString);
        //
        Dictionary<Videos2Links.ConfigData.KeyName, string> dc;
        //
        //====================================================================================================================
        public MainWindow()
        {
            InitializeComponent();
            //
            progressBar1.Minimum = 0;
            progressBar1.Maximum = 100;
            //progresBar1.ToolTipText = "";
            //
            try
            {
                stat = new DbStatistics(DbStatistics. dbConnectionString);
            }
            catch(Exception e0)
            {
                string s = "";
                s += e0.Message + Environment.NewLine;
                s += Environment.NewLine;
                s += Environment.NewLine;
                s += e0.StackTrace + Environment.NewLine;
                s += Environment.NewLine;
                s += Environment.NewLine;
                s += e0.Source + Environment.NewLine;
                s += Environment.NewLine;
                s += Environment.NewLine;
                s += e0.InnerException.Message + Environment.NewLine;
                s += Environment.NewLine;
                System.IO.File.WriteAllText("Err-DbStatistics.txt", s, Encoding.UTF8);
                //
                MessageBox.Show(e0.Message + e0.StackTrace, "DbStatistics", MessageBoxButton.OK, MessageBoxImage.Error);
                this.Close();
            }
            Task.Factory.StartNew(new Action(DbStatistics.CreateDbIfNeeded));
            //
            try
            {
                dc = Videos2Links.ConfigData.ReadConfig();
            }
            catch (Exception e)
            {
                MessageBox.Show(string.Format("Error in {0}: {1}", Videos2Links.ConfigData.ConfigFileName, e.Message), "ConfigData.ReadConfig()", MessageBoxButton.OK, MessageBoxImage.Error);
                System.IO.File.WriteAllLines("errors.txt", new[] { e.Message + Environment.NewLine }, Encoding.UTF8);
                //
                return;
            }
            //
        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
            source.AddHook(WndProc);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                win1_SizeChanged(null, null);
                //
                wfh.Child = vlc;
                //
                vlc.AllowDrop = false;
                vlc.Volume = 100;
                vlc.BackColor = System.Drawing.Color.DarkBlue;
                vlc.AutoLoop = false;
                vlc.AutoPlay = false;
                vlc.Toolbar = false;
                vlc.FullscreenEnabled = false;
                //
                //
                vlc.MediaPlayerEndReached += axVLCPlugin21_MediaPlayerEndReached;
                vlc.play += axVLCPlugin21_play;
                vlc.stop += axVLCPlugin21_stop;
                vlc.pause += axVLCPlugin21_pause;
                vlc.MediaPlayerTimeChanged += axVLCPlugin21_MediaPlayerTimeChanged;
                //
                dt.IsEnabled = false;
                dt.Interval = new TimeSpan(500000L);
                dt.Tick += dt_Tick;
            }
            catch (Exception e1)
            {
                MessageBox.Show(e1.Message + e1.StackTrace, "Window_Loaded", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        //====================================================================================================================
        private System.Windows.Threading.DispatcherTimer dt01 = new System.Windows.Threading.DispatcherTimer() { IsEnabled = false, Interval = new TimeSpan(0, 0, 0, 0, 100) };
        private System.Threading.Timer tt02 = null;
        //private System.Windows.Threading.DispatcherTimer dt02 = new System.Windows.Threading.DispatcherTimer() { IsEnabled = false, Interval = new TimeSpan(0, 0, 0, 1, 0) };
        //public delegate void TimerCallback (Object state)

        void dt01_Tick(object sender, EventArgs e)
        {
            dt01.IsEnabled = false;
            //dt02.IsEnabled = true;
            tt02 = new System.Threading.Timer(tt02_Tick, null, new TimeSpan(0,0,1), new TimeSpan(1,0,0,0,0));
            //
            CLogger.Write("Dispatcher.BeginInvoke(new Action(() => stopPlaying()))");
            Dispatcher.BeginInvoke(new Action(() => stopPlaying()));
        }
        void dt02_Tick(object sender, EventArgs e)
        {
            //dt02.IsEnabled = false;
            //
            CLogger.Write("Application.Current.Shutdown()");
            Application.Current.Shutdown();
        }
        private void tt02_Tick(object state)
        {
            //Application.Current.Dispatcher.Invoke(new Action(() => Application.Current.Shutdown()));
            Application.Current.Dispatcher.InvokeShutdown();
        }
        private static int WM_QUERYENDSESSION = 0x11;
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_QUERYENDSESSION)
            {
                CLogger.Write("WM_QUERYENDSESSION");
                dt01.Tick += dt01_Tick; dt01.IsEnabled = true;
                //dt02.Tick += dt02_Tick;
                //
                handled = true;
                //
            }
            return IntPtr.Zero;
        }

        public void Dispose()
        {
            if(null != stat)
            {
                stat.Dispose();
            }
            if (null != vlc)
            {
                vlc.Dispose();
                vlc = null;
            }
            if(null != tt02)
            {
                tt02.Dispose();
            }
        }

        //====================================================================================================================
        private object playO = new object();
        private void playCurrent()
        {
            lock (playO)
            {
                win1.Title = "";
                progressBar1.Value = 0;
                //
                if (0 == filesToPlay.Count) return;
                //
                win1.Title = System.IO.Path.GetFileName(filesToPlay[currentPlaying].OriginalFile);
                doEvents();
                vlc.playlist.items.clear();
                do { doEvents(); } while (0 != vlc.playlist.items.count);
                vlc.playlist.add((new Uri(filesToPlay[currentPlaying].ResolvedFile)).ToString());
                doEvents();
                vlc.playlist.playItem(0);
                do { doEvents(); } while (!vlc.playlist.isPlaying);
                //
                progressBar1.ToolTip = System.IO.Path.GetFileName(filesToPlay[currentPlaying].OriginalFile);
                stat.incrementPlayed(System.IO.Path.GetFileName(filesToPlay[currentPlaying].OriginalFile));
                //
                SetButtonImage(buttonPlay, "Stop");
                //
                progressBar1.Value = 0;
            }
        }

        private object stopO = new object();
        private void stopPlaying()
        {
            lock (stopO)
            {
                win1.Title = "";
                progressBar1.Value = 0;
                //
                SetButtonImage(buttonPlay, "Play");
                //
                progressBar1.ToolTip = "";
                //
                doEvents();
                vlc.playlist.pause();
                doEvents();
                vlc.playlist.stop();// hangs here *****
                do { doEvents(); } while (vlc.playlist.isPlaying);
                vlc.playlist.items.clear();
                do { doEvents(); } while (0 != vlc.playlist.items.count);
            }
            //
        }
        //====================================================================================================================
        //private void axVLCPlugin21_MediaPlayerEndReached(object sender, EventArgs e)
        private void axVLCPlugin21_MediaPlayerEndReached(object sender, EventArgs e)
        {
            currentPlaying++;
            progressBar1.Value = 100;
            //
            if (currentPlaying >= filesToPlay.Count)
            {
                doEvents();
                stopPlaying();
                doEvents();
                filesToPlay.Clear();
                currentPlaying = 0;
                return;
            }
            playCurrent();
        }
        //====================================================================================================================
        //private void axVLCPlugin21_play(object sender, EventArgs e)
        private void axVLCPlugin21_play(object sender, EventArgs e)
        {
            if (0 == filesToPlay.Count()) return;
            //
            if (isBetweenTrack) return;
            //
            if (this.WindowState != System.Windows.WindowState.Maximized)
            {
                EnterFullScreenMode();
            }
        }

        //private void axVLCPlugin21_pause(object sender, EventArgs e)
        private void axVLCPlugin21_pause(object sender, EventArgs e)
        {
            if (isBetweenTrack) return;
            //
            if (this.WindowState != System.Windows.WindowState.Normal)
            {
                LeaveFullScreenMode();
            }
        }

        //private void axVLCPlugin21_stop(object sender, EventArgs e)
        private void axVLCPlugin21_stop(object sender, EventArgs e)
        {
            if (isBetweenTrack) return;
            //
            if (this.WindowState != System.Windows.WindowState.Normal)
            {
                LeaveFullScreenMode();
            }
        }
        //====================================================================================================================
        private void win1_DragOver(object sender, DragEventArgs e)
        {
            e.Effects = DragDropEffects.Copy;
        }

        private void win1_DragEnter(object sender, DragEventArgs e)
        {
            e.Effects = DragDropEffects.Copy;
        }

        private void win1_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                //
                e.Effects = DragDropEffects.Copy;
                //
                stopPlaying();
                filesToPlay.Clear();
                currentPlaying = 0;
                //
                string[] droppedFiles = (string[])e.Data.GetData(DataFormats.FileDrop);
                //
                //
                // >1 files/dirs: wczytujemy wszystkie, gramy od 0
                // 1: 
                //
                if (droppedFiles.Length > 1)
                {
                    foreach (string droppedFile in droppedFiles)
                    {
                        List<MediaFile> mf = DirectoryCache.GetFilesFromDirectory(droppedFile);
                        if (0 == mf.Count) continue;
                        filesToPlay.Add(mf[0]);
                    }
                    //
                    currentPlaying = 0;
                    //
                }
                else
                {
                    filesToPlay = DirectoryCache.GetFilesFromDirectory(droppedFiles[0]);
                    currentPlaying = 0;
                    //
                    sCfg.Load(droppedFiles[0]);
                    setRandom(sCfg.GetValueBool("Random"));
                    //
                }
                //
                //
                //
                if (isRandom && filesToPlay.Count > 1)
                {
                    Random rnd = new Random();
                    filesToPlay = filesToPlay.OrderBy(x => rnd.Next()).ToList<MediaFile>();
                    currentPlaying = 0;
                }
                //
                //
                if (filesToPlay.Count > 0)
                {
                    playCurrent();
                }
                //
                //
            }
            //
            e.Effects = DragDropEffects.None;
            //
        }
        //====================================================================================================================
        private class ItemData
        {
            public bool isInCenter;
            public int Width;

        }

        private void win1_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            //
            // Element, który ma być wycentrowany ma mieć w Tag wisaną '*'
            // Położenie jest regulowane szerokością zerowego elementu: Label
            //
            List<ItemData> ids = new List<ItemData>();
            //
            int freeSpaceWidth = CClientAreaSize.GetClientWidth(this);
            //int freeSpaceWidth = (int)win1.ActualWidth - (2*(int)SystemParameters.ResizeFrameVerticalBorderWidth);
            int widthOfAllElements = 0;
            //
            for (int k = 0; k < toolStrip.Children.Count; k++)
            {
                var x = toolStrip.Children[k];
                Label l = x as Label;
                Button b = x as Button;
                ProgressBar p = x as ProgressBar;
                if (null != l)
                {
                    ids.Add(new ItemData() { isInCenter = ("*" == (string)l.Tag), Width = (int)l.Width });
                    widthOfAllElements += (int)l.Width;
                }
                else if (null != b)
                {
                    ids.Add(new ItemData() { isInCenter = ("*" == (string)b.Tag), Width = (int)b.Width });
                    widthOfAllElements += (int)b.Width;
                }
                else if (null != p)
                {
                    ids.Add(new ItemData() { isInCenter = ("*" == (string)p.Tag), Width = (int)p.Width });
                    widthOfAllElements += (int)p.Width;
                }
                else
                {
                    ids.Add(new ItemData() { isInCenter = false, Width = 1 });
                    widthOfAllElements += 1;
                }
            }
            //
            //
            //
            //
            //
            //
            //
            //
            //
            int widthOfCenterElement = (from x in ids where x.isInCenter select x.Width).SingleOrDefault<int>();
            //
            int widthElementsWithoutPad = 0;
            for (int i = 1; i < ids.Count; i++)
            {
                if (ids[i].isInCenter) break;
                widthElementsWithoutPad += ids[i].Width;
            }
            //
            //
            //
            if ((widthElementsWithoutPad + 2) >= freeSpaceWidth)
            {
                (toolStrip.Children[0] as Label).Width = 1;
                return;
            }
            //
            //
            int widhOfZeroElement = ((freeSpaceWidth - 2) / 2) - ((widthElementsWithoutPad + (widthOfCenterElement / 2)));
            //
            if ((widhOfZeroElement + widthElementsWithoutPad) < (freeSpaceWidth - 2))
            {
                (toolStrip.Children[0] as Label).Width = widhOfZeroElement;
            }
            else
            {
                widhOfZeroElement = (freeSpaceWidth - 1) - widthElementsWithoutPad;
                if (widhOfZeroElement < 0) widhOfZeroElement = 1;
                (toolStrip.Children[0] as Label).Width = widhOfZeroElement;
            }

        }
        //====================================================================================================================
    }//class
}//namespace
